/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cloud_model.h"
#include "cloud_model_diagnosis.h"
#include "cloud_model_image.h"
#include "cloud_model_realtime_audio.h"
#include "common_config_manager.h"
#include "utils_log.h"
#include <nlohmann/json.hpp>

namespace El {
namespace Cloud {

AliyunService::AliyunService() : started_(false) {}

AliyunService::~AliyunService()
{
    Stop();
}

AliyunService &AliyunService::GetInstance()
{
    static AliyunService instance;
    return instance;
}

bool AliyunService::Start()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (started_) {
        EL_DEBUG("Aliyun service already started");
        return true;
    }

    try {
        // 检查云模型服务是否启用
        auto config = El::Common::ConfigManager::GetInstance().GetConfig("/cloud_model");
        if (!config.is_null()) {
            bool enabled = config.value("enabled", false);
            if (!enabled) {
                EL_INFO("Cloud model service is disabled in configuration");
                return true; // 返回true表示不是错误，而是配置禁用
            }
        } else {
            EL_WARN("Cloud model configuration not found, service disabled by default");
            return true;
        }

        EL_INFO("Starting aliyun service...");

        // 1. 启动诊断服务
        EL_DEBUG("Starting cloud model diagnosis...");
        if (!CloudModelDiagnosis::GetInstance().Start()) {
            EL_ERROR("Failed to start cloud model diagnosis");
            return false;
        }
        EL_DEBUG("Cloud model diagnosis started successfully");

        // 2. 启动图像识别服务
        EL_DEBUG("Starting cloud model image...");
        CloudModelImage::GetInstance().Start();
        EL_DEBUG("Cloud model image started successfully");

        // 3. 启动实时音频服务
        EL_DEBUG("Starting cloud model realtime audio...");
        if (CloudModelRealtimeAudio::GetInstance().Start()) {
            EL_DEBUG("Cloud model realtime audio started successfully");

            // 读取配置判断是否启用VAD自动模式
            auto realtimeAudioConfig = config.value("realtime_audio", nlohmann::json{});
            if (!realtimeAudioConfig.is_null()) {
                std::string mode = realtimeAudioConfig.value("mode", std::string("manual"));

                if (mode == "vad") {
                    // VAD模式: 自动语音检测,立即启动音频流
                    autoModeEnabled_ = true;
                    EL_INFO("Realtime audio configured in VAD mode, starting automatically...");
                    if (!StartRealtimeAudioAutoMode()) {
                        EL_WARN("Failed to start realtime audio in VAD mode");
                    }
                } else if (mode == "manual") {
                    // 手动控制模式: 仅启动服务,等待API调用
                    EL_INFO("Realtime audio in manual mode, waiting for API trigger");
                } else {
                    EL_WARN("Unknown realtime audio mode '{}', using manual mode as default", mode);
                }
            } else {
                EL_WARN("Realtime audio config not found, using manual mode as default");
            }
        } else {
            EL_WARN("Failed to start cloud model realtime audio (optional feature)");
        }

        started_ = true;
        EL_INFO("Aliyun service started");
        return true;

    } catch (const std::exception &e) {
        EL_ERROR("Aliyun service start exception: {}", e.what());
        return false;
    } catch (...) {
        EL_ERROR("Aliyun service start unknown exception");
        return false;
    }
}

bool AliyunService::Stop()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!started_) {
        EL_DEBUG("Aliyun service not started");
        return true;
    }

    // 检查云模型服务是否被配置禁用
    auto config = El::Common::ConfigManager::GetInstance().GetConfig("/cloud_model");
    if (!config.is_null()) {
        bool enabled = config.value("enabled", false);
        if (!enabled) {
            EL_DEBUG("Cloud model service is disabled in configuration, nothing to stop");
            return true;
        }
    }

    try {
        EL_INFO("Stopping aliyun service...");

        // 1. 停止实时音频服务
        EL_DEBUG("Stopping cloud model realtime audio...");
        auto &cloudAudio = CloudModelRealtimeAudio::GetInstance();
        // 如果有活动会话,先停止
        if (cloudAudio.GetSessionState() != RealtimeSessionState::Disconnected) {
            StopRealtimeAudio();
        }
        cloudAudio.Stop();

        // 2. 停止图像识别服务
        EL_DEBUG("Stopping cloud model image...");
        CloudModelImage::GetInstance().Stop();

        // 注意: CloudModelDiagnosis 目前没有 Stop 方法

        started_ = false;
        EL_INFO("Aliyun service stopped");
        return true;

    } catch (const std::exception &e) {
        EL_ERROR("Aliyun service stop exception: {}", e.what());
        return false;
    } catch (...) {
        EL_ERROR("Aliyun service stop unknown exception");
        return false;
    }
}

bool AliyunService::IsStarted() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return started_;
}

bool AliyunService::StartRealtimeAudioAutoMode()
{
    auto &cloudAudio = CloudModelRealtimeAudio::GetInstance();

    // 1. 设置回调
    RealtimeAudioCallbacks callbacks;

    callbacks.onStateChanged = [](RealtimeSessionState state) {
        EL_INFO("Realtime audio state changed to: {}", static_cast<int>(state));
    };

    callbacks.onTextReceived = [](const std::string &text) {
        EL_INFO("AI text: {}", text);
        // TODO: 可以通过Event系统发布给Web界面显示
        // El::Common::Event::GetInstance().Notify("realtime_audio.text", {{"text", text}});
    };

    callbacks.onAudioReceived = [](const std::vector<uint8_t> &audioData) {
        EL_DEBUG("Received audio response: {} bytes", audioData.size());
    };

    callbacks.onSpeechStart = []() { EL_INFO("User started speaking"); };

    callbacks.onSpeechEnd = []() { EL_INFO("User stopped speaking"); };

    callbacks.onError = [](const std::string &error) { EL_ERROR("Realtime audio error: {}", error); };

    // 2. 创建会话
    if (!cloudAudio.CreateSession(callbacks)) {
        EL_ERROR("Failed to create realtime audio session");
        return false;
    }
    EL_INFO("Realtime audio session created");

    // 3. 启用自动音频流 - 直接从顶层配置读取channel_id
    auto config = El::Common::ConfigManager::GetInstance().GetConfig("/cloud_model/realtime_audio");
    int32_t channelId = config.value("channel_id", 0);

    if (!cloudAudio.EnableAutoAudioStream(channelId)) {
        EL_ERROR("Failed to enable auto audio stream");
        cloudAudio.DeleteSession();
        return false;
    }

    EL_INFO("Realtime audio VAD mode started successfully (channel: {})", channelId);
    return true;
}

bool AliyunService::StartRealtimeAudio()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!started_) {
        EL_ERROR("Cannot start realtime audio: AliyunService not started");
        return false;
    }

    if (autoModeEnabled_) {
        EL_WARN("Realtime audio is in VAD mode, cannot manually start");
        return false;
    }

    auto &cloudAudio = CloudModelRealtimeAudio::GetInstance();

    // 检查是否已有会话
    if (cloudAudio.GetSessionState() != RealtimeSessionState::Disconnected) {
        EL_WARN("Realtime audio session already exists");
        return true; // 已经存在,返回成功
    }

    // 设置回调（与自动模式相同）
    RealtimeAudioCallbacks callbacks;

    callbacks.onStateChanged = [](RealtimeSessionState state) {
        EL_INFO("Realtime audio state: {}", static_cast<int>(state));
    };

    callbacks.onTextReceived = [](const std::string &text) { EL_INFO("AI: {}", text); };

    callbacks.onAudioReceived = [](const std::vector<uint8_t> &audioData) {
        EL_DEBUG("Received audio: {} bytes", audioData.size());
    };

    callbacks.onSpeechStart = []() { EL_INFO("User started speaking"); };

    callbacks.onSpeechEnd = []() { EL_INFO("User stopped speaking"); };

    callbacks.onError = [](const std::string &error) { EL_ERROR("Realtime audio error: {}", error); };

    // 创建会话
    if (!cloudAudio.CreateSession(callbacks)) {
        EL_ERROR("Failed to create realtime audio session");
        return false;
    }

    // 启用音频流 - 直接从顶层配置读取channel_id
    auto config = El::Common::ConfigManager::GetInstance().GetConfig("/cloud_model/realtime_audio");
    int32_t channelId = config.value("channel_id", 0);

    if (!cloudAudio.EnableAutoAudioStream(channelId)) {
        EL_ERROR("Failed to enable audio stream");
        cloudAudio.DeleteSession();
        return false;
    }

    EL_INFO("Realtime audio started manually (channel: {})", channelId);
    return true;
}

bool AliyunService::StopRealtimeAudio()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (autoModeEnabled_) {
        EL_WARN("Realtime audio is in VAD mode, cannot manually stop");
        return false;
    }

    auto &cloudAudio = CloudModelRealtimeAudio::GetInstance();

    // 检查会话状态
    if (cloudAudio.GetSessionState() == RealtimeSessionState::Disconnected) {
        EL_WARN("No active realtime audio session to stop");
        return false;
    }

    // 停止音频流
    cloudAudio.DisableAutoAudioStream();

    // 删除会话
    cloudAudio.DeleteSession();

    EL_INFO("Realtime audio stopped");
    return true;
}

nlohmann::json AliyunService::GetRealtimeAudioStatus() const
{
    std::lock_guard<std::mutex> lock(mutex_);

    nlohmann::json status;

    if (!started_) {
        status["service_started"] = false;
        status["mode"] = "unknown";
        status["state"] = "Disconnected";
        status["stream_active"] = false;
        return status;
    }

    auto &cloudAudio = CloudModelRealtimeAudio::GetInstance();

    status["service_started"] = true;
    status["mode"] = autoModeEnabled_ ? "vad" : "manual";

    auto state = cloudAudio.GetSessionState();
    status["state"] = [state]() -> std::string {
        switch (state) {
            case RealtimeSessionState::Disconnected:
                return "Disconnected";
            case RealtimeSessionState::Connecting:
                return "Connecting";
            case RealtimeSessionState::Connected:
                return "Connected";
            case RealtimeSessionState::Speaking:
                return "Speaking";
            case RealtimeSessionState::Responding:
                return "Responding";
            case RealtimeSessionState::Error:
                return "Error";
            default:
                return "Unknown";
        }
    }();
    status["stream_active"] = (state == RealtimeSessionState::Connected || state == RealtimeSessionState::Speaking ||
                               state == RealtimeSessionState::Responding);

    return status;
}

} // namespace Cloud
} // namespace El
